﻿using RosNode;
using WebsocketApp;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Timers;
using System.Windows.Input;
using System.Windows.Media;
using System.Collections.ObjectModel;
using System.Collections;
using Newtonsoft.Json;

namespace RosConsole.Domain
{
    class ControlsViewModel : ViewModelBase
    {
        protected Timer timer;
        protected WingNode node;
        protected WebsocketNode websocket_node;
        readonly List<string> ViewProperties = new()
        {
            nameof(PidEnable),
            nameof(RosReady),
            nameof(ServerOnline)
        };
        public ControlsViewModel()
        {
            node = WingNode.CreateInstance();
            websocket_node = WebsocketNode.CreateInstance();
            WebsocketServerAddr = websocket_node.ServerAddress;
            timer = new(200)
            {
                AutoReset = true,
                Enabled = true
            };
            timer.Elapsed += (object sender, ElapsedEventArgs e) =>
            {
                foreach (var s in ViewProperties)
                {
                    OnPropertyChanged(s);
                }
            };

            SetMoveDistance = new AnotherCommandImplementation(_ => node.MoveDistance(ManuallyInput, MoveDistance, TargetX, TargetY));
            ConnectServer = new AnotherCommandImplementation(async _ =>
           {
               bool ret = await websocket_node.Connect(WebsocketServerAddr);
               if (ret)
               {
                   CloudColor = new SolidColorBrush(Colors.MediumSlateBlue);
               }
               else
               {
                   CloudColor = new SolidColorBrush(Colors.LightGray);
               }
           });

            Disconnect = new AnotherCommandImplementation(async _ =>
            {
                await websocket_node.Close();
                CloudColor = new SolidColorBrush(Colors.LightGray);
            });

            void ReadSettings(string setting, ref ObservableCollection<NavigationTaskItem> value)
            {
                bool navlist_got = false;
                if (setting != null)
                {
                    try
                    {
                        var n = JsonConvert.DeserializeObject<List<NavigationTaskItem>>(setting);
                        if (n != null)
                        {
                            value = new ObservableCollection<NavigationTaskItem>(n);
                            navlist_got = true;
                        }
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine(e);
                    }
                }
                if (!navlist_got)
                {
                    value = new ObservableCollection<NavigationTaskItem>() {
                        new NavigationTaskItem()
                    };
                }                
            }

            EmptyNavigation = new ObservableCollection<NavigationTaskItem>() {
                new NavigationTaskItem()
                };

            ReadSettings(Properties.Settings.Default.NavigationList, ref NavigationItems);
            ReadSettings(Properties.Settings.Default.ReturnFromCarPoint, ref ReturnFromCarPoint);
            ReadSettings(Properties.Settings.Default.EnterCarPoint, ref EnterCarPoint);
            ReadSettings(Properties.Settings.Default.GoChargingPoint, ref GoChargingPoint);

            SaveNavigationItems();

            ResetPoints = new AnotherCommandImplementation(_ =>
            {
                for (int i = NavigationItems.Count; i > 1; i--)
                {
                    NavigationItems.Remove(NavigationItems[i - 1]);
                }
                OnPropertyChanged(nameof(NavigationItems));
            });

            SendMessage = new AnotherCommandImplementation(async _ =>
            {
                await websocket_node.SendWingbotMessage(MessageHelper.MsgIds[SelectedMessage], SelectedNavigationItems.ToList());
                SaveNavigationItems();
            });

            ChangeSelectedItems();
        }

        private void SaveNavigationItems()
        {
            Properties.Settings.Default.NavigationList = JsonConvert.SerializeObject(NavigationItems.ToList());
            Properties.Settings.Default.EnterCarPoint = JsonConvert.SerializeObject(EnterCarPoint);
            Properties.Settings.Default.ReturnFromCarPoint = JsonConvert.SerializeObject(ReturnFromCarPoint);
            Properties.Settings.Default.GoChargingPoint = JsonConvert.SerializeObject(GoChargingPoint);
            Properties.Settings.Default.Save();
        }

        private string _WebsocketServerAddr;
        public string WebsocketServerAddr { get => _WebsocketServerAddr; set => SetProperty(ref _WebsocketServerAddr, value); }

        private Brush _cloudColor = new SolidColorBrush(Colors.LightGray);
        public Brush CloudColor
        {
            get => _cloudColor;
            private set => SetProperty(ref _cloudColor, value);
        }

        public string[] MessageTypes { get => MessageHelper.MsgIds.Keys.ToArray(); }

        public bool PidEnable { get => node.driver_state.PidEnable; }
        public bool RosReady { get => node.PubReady; }

        private double _MoveDistance;
        public double MoveDistance { get => _MoveDistance; set => SetProperty(ref _MoveDistance, value); }

        private bool _ManuallyInput = false;
        public bool ManuallyInput { get => _ManuallyInput; set => SetProperty(ref _ManuallyInput, value); }

        private double _TargetX = 0.0;
        private double _TargetY = 0.0;

        public double TargetX { get => _TargetX; set => SetProperty(ref _TargetX, value); }
        public double TargetY { get => _TargetY; set => SetProperty(ref _TargetY, value); }
        public bool ServerOnline { get => websocket_node.Online; }

        private string _SelectedMessage = MessageHelper.MsgIds.Keys.ToArray()[0];
        public string SelectedMessage { get => _SelectedMessage; set => SetProperty(ref _SelectedMessage, value); }

        private ObservableCollection<NavigationTaskItem> NavigationItems;     //导航点
        private ObservableCollection<NavigationTaskItem> EmptyNavigation;     //空任务点，用于抬车，卸车
        private ObservableCollection<NavigationTaskItem> EnterCarPoint;       //进入车底的坐标
        private ObservableCollection<NavigationTaskItem> ReturnFromCarPoint;  //离开车底后的坐标
        private ObservableCollection<NavigationTaskItem> GoChargingPoint;     //充电桩坐标
        private ObservableCollection<NavigationTaskItem> _SelectedNavigationItems;
        public ObservableCollection<NavigationTaskItem> SelectedNavigationItems { get => _SelectedNavigationItems; set => SetProperty(ref _SelectedNavigationItems, value); }
        public ICommand SetMoveDistance { get; }
        public ICommand ConnectServer { get; }
        public ICommand Disconnect { get; }
        public ICommand SendMessage { get; }
        public ICommand ResetPoints { get; }
        public void ChangeSelectedItems()
        {
            SelectedNavigationItems = SelectedMessage switch
            {
                "Navigation" => NavigationItems,
                "EnterCar" => EnterCarPoint,
                "ReturnFromCar" => ReturnFromCarPoint,
                "GoCharging" => GoChargingPoint,
                _ => EmptyNavigation,
            };
        }
    }
}
